#pragma once

#include "noncopyable.h"
#include "Timestamp.h"
#include "CurrentThread.h"


#include <vector>
#include <functional>
#include <atomic>
#include <mutex>
#include <memory>


class Channel;
class Poller;

// 事件循环类       主要包含Channel类和Poller类(封装了epoll)
class EventLoop
{
public:
    using Functor = std::function<void()>;

    EventLoop();
    ~EventLoop();

    // 开启事件循环
    void loop();
    // 退出事件循环
    void quit();

    Timestamp pollReturnTime() const { return m_pollReturnTime; }

    // 在当前loop中执行cb
    void runInLoop(Functor cb);
    // 把cb放入到队列中，唤醒loop所在的线程，执行cb
    void queueInLoop(Functor cb);

    // 用来唤醒loop所在的线程
    void wakeup();

    // Channel通过EventLoop的方法来操作Poller
    void updateChannel(Channel* channel);
    void removeChannel(Channel* channel);
    bool hasChannel(Channel* channel);

    // 判断EventLoop对象是否在自己的线程里面
    bool isInLoopThread() const { return m_threadId == CurrentThread::tid(); }

private:
    // 唤醒对应线程的loop
    void handleRead();
    // 执行回调
    void doPendingFunctors();

private:
    using ChannelList = std::vector<Channel*>;

    std::atomic_bool m_looping; 
    std::atomic_bool m_quit; // 标识退出loop循环

    const pid_t m_threadId; // 记录创建eventloop所在线程的id

    Timestamp m_pollReturnTime; // Poller返回发生事件的Channels的时间点
    std::unique_ptr<Poller> m_poller;

    int m_wakeupFd; // 当mainLoop获取一个新用户的channel，通过轮询算法选择一个subLoop，通过该成员唤醒subLoop处理Channel
    std::unique_ptr<Channel> m_wakeupChannel;

    ChannelList m_activeChannels;   // 保存已激活的Channels的动态数组

    std::atomic_bool m_callingPendingFunctors;  // 标识当前loop是否有需要执行的回调操作
    std::vector<Functor> m_pendingFunctors;     // 存放loop需要执行的所有回调操作(一般用来存储不在对应线程loop的回调操作)
    std::mutex m_mutex; // 用来保护上面vector容器(ChannelList)的线程安全操作
};